home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac-Source 1994 July
/
Mac-Source_July_1994.iso
/
C and C++
/
Libraries
/
ExceptionHandler-C-src
/
GetZoneList (LightSpeed).c
< prev
next >
Wrap
Text File
|
1990-09-10
|
17KB
|
620 lines
/* ------------------------------------------------------------------------------
# Modified for LightSpeed C by R. Mark Fleming Jan. 30, 1990
#
# Apple Macintosh Developer Technical Support
#
# AppleTalk GetZoneList Sample Application
#
# GetZoneList
#
# GetZoneList.c - C Source
#
# Copyright © 1989 Apple Computer, Inc.
# All rights reserved.
#
# Versions: 1.0 11/88
# 1.1 10/89
#
# Components: GetZoneList.p October 1, 1989
# GetZoneList.c October 1, 1989
# GetZoneList.r October 1, 1989
# PGetZoneList.make October 1, 1989
# CGetZoneList.make October 1, 1989
#
# Requirements:
# UFailure.p November 1, 1988
# UFailure.inc1.p November 1, 1988
# UFailure.a November 1, 1988
#
# GetZoneList is a sample application that uses
# AppleTalk ATP and ZIP to obtain a list of zones
# on an AppleTalk internet.
#
# GetZoneList also demonstrates using a signal, or
# failure-catching mechanism to recover from error
# situations. Since C does not allow nested procedures
# a la Pascal, a few modifications were made to incorporate
# the failure handling and keep this sample fairly close in
# design to the Pascal sample.
# (Gee, thanks a lot M2 for using nested procs. - pvh)
#
# GetZoneList is based on MACDTS Sample.c. For more
# description and explanation of the non-example
# specific areas of this application, please refer to
# either Sample.p or TESample.c.
# PSendRequest() & GetBridgeAddress() - nAppleTalk library
------------------------------------------------------------------------------ */
#include "MyExceptionHandler.h"
#include "GetZoneInclude.h"
/* Globs */
SysEnvRec gMac; /* set up by Initialize */
Boolean gHasWaitNextEvent; /* set up by Initialize */
Boolean gInBackground; /* maintained by Initialize and DoEvent */
ListHandle gList; /* the list to be filled with zone names */
/* globals added for C sample use as the Pascal
example used those horrid :-) nested procedures! */
ATPPBPtr gATPPBPtr; /* the parameter block for GetZoneList call */
Ptr gZones; /* the data buffer for GetZoneList call */
DialogPtr gErrDlg; /* Dialog used for displaying zone list */
Boolean TrapAvailable(short, int);
void FailOSErrMsg(result, message)
short result;
short message;
{
if (result != noErr) Failure(result, message);
} /* SignalOSErrMsg */
void FailnilMsg(p, message)
Ptr p;
short message;
{
if (p == nil) Failure(memFullErr, message);
} /* FailNILMsg */
void AlertUser(error, message)
/* Display an alert to inform the user of an error. Message acts as an
index into a STR# resource of error messages. if no message is given,
i.e. = 0, then use a standard message. if error is not noErr then
display it as well. */
short error;
long message;
{
Str255 msg1, msg2;
short itemHit;
if (message == 0L) message = eStandardErr;
GetIndString(msg1, sErrStrings, message);
if (error == noErr) msg2[0] = '';
else NumToString(error, msg2);
ParamText(msg1, msg2, "\p", "\p");
itemHit = Alert(rUserAlert, nil);
} /* AlertUser */
Boolean IsDAWindow(window)
WindowPtr window;
{
if (window == nil) return (false);
else /* DA windows have negative windowKinds */
return ((WindowPeek) window)->windowKind < 0;
} /* IsDAWindow */
Boolean IsAppWindow(window)
WindowPtr window;
{
short windowKind;
if ( window == nil ) return false;
else {
/* application windows have
windowKinds >= userKind (8) or dialogKind (2) */
windowKind = ((WindowPeek) window)->windowKind;
return (windowKind >= userKind) || (windowKind == dialogKind);
}
} /* IsAppWindow */
void ZoneListCleanUp()
{
if (gATPPBPtr != nil)
DisposPtr((Ptr)gATPPBPtr); /* get rid of pb block */
if (gZones != nil) DisposPtr(gZones); /* and buffer */
} /* ZoneListCleanUp */
pascal void HandleZoneListErr(error, message)
short error;
long message;
{
ZoneListCleanUp(); /* get rid of allocated junk */
} /* HandleZoneListErr */
void BuildZoneList()
/* Create the list of zones on the network. Find a bridge to talk to , if one is
present, then ask it for zone names. Add the names to the list in the dialog. */
{
BDSElement dBDS; /* the BDS for GetZoneList call */
Ptr dCurr; /* the data buffer for GetZoneList call */
short dIndex, dCount;
short ignore;
Cell cSize;
FailInfo fi;
gATPPBPtr = nil; /* init some important variables*/
gZones = nil;
CatchCFailures(&fi, HandleZoneListErr);
gATPPBPtr = (ATPPBPtr)NewPtr(sizeof(ATPParamBlock));
FailnilMsg(gATPPBPtr, eNoMemory);
gZones = NewPtr(kZonesSize);
FailnilMsg(gZones, eNoMemory);
dBDS.buffSize = kZonesSize; /* set up BDS */
dBDS.buffPtr = gZones;
gATPPBPtr->ATPatpFlags = 0;
FailOSErrMsg(GetNodeAddress(&ignore, &gATPPBPtr->ATPaddrBlock.aNet), eAppleTalk); /* get net of bridge */
if (gATPPBPtr->ATPaddrBlock.aNet == 0) Failure(0, eNoZones); /* bail if no zones present */
gATPPBPtr->ATPaddrBlock.aNode = GetBridgeAddress(); /* get node of bridge */
gATPPBPtr->ATPaddrBlock.aSocket = kZIPSocket; /* the socket we want */
gATPPBPtr->ATPreqLength = 0;
gATPPBPtr->ATPreqPointer = nil;
gATPPBPtr->ATPbdsPointer = (Ptr) &dBDS;
gATPPBPtr->ATPnumOfBuffs = 1;
gATPPBPtr->ATPtimeOutVal = kATPTimeOutVal;
gATPPBPtr->ATPretryCount = kATPRetryCount;
dIndex = 1;
dCount = 0;
SetPt(&cSize, 0, 0); /* we always stuff into first */
do {
gATPPBPtr->ATPuserData = kGZLCall + dIndex; /* indicate GetZoneList request */
FailOSErrMsg(PSendRequest(gATPPBPtr, false), eAppleTalk); /* send sync request */
dCount = dCount + dBDS.userBytes & kZoneCount; /* find out how many returned */
dCurr = gZones; /* put current pointer at start */
do { /* get each zone */
ignore = LAddRow(1, 0, gList); /* create new cell at start */
LSetCell((Ptr)dCurr + 1L, (short) *dCurr, cSize, gList); /* stuff in zone */
dCurr = (Ptr)(dCurr + *dCurr + 1 ); /* bump up current pointer */
dIndex = dIndex + 1; /* increment which zone */
} while(! (dIndex > dCount));
} while ((dBDS.userBytes & kMoreZones) == 0); /* keep going until none left */
ZoneListCleanUp();
Success(&fi);
} /* BuildZoneList */
pascal void ZoneListDraw(dlg, item)
DialogPtr dlg;
short item;
{
/* The user item void for the zone list user item and default
box user item in the dialog. Draw the list and the frame that goes with it.
Draw the default box around the OK button */
GrafPtr port;
short kind;
Handle h;
Rect r;
PenState ps;
GetPort(&port); /* save old port */
SetPort(dlg); /* make dialog port */
switch (item) {
case dZoneList:
LUpdate(dlg->visRgn, gList); /* re-draw list */
GetDItem(dlg, dZoneList, &kind, &h, &r);
InsetRect(&r, kListInset, kListInset);
FrameRect(&r); /* re-draw frame */
break;
case dDefault:
GetDItem(dlg, dDefault, &kind, &h, &r);
GetPenState(&ps);
PenSize(3, 3);
InsetRect(&r, -4, -4);
FrameRoundRect(&r, 16, 16); /* draw default box */
SetPenState(&ps);
break;
}
SetPort(port); /* restore old port */
} /* ZoneListDraw */
pascal Boolean ListFilter (dlg, event, item)
DialogPtr dlg;
EventRecord *event;
short *item;
{
/* Passed as parameter to ModalDialog. Handle key presses and mouse clicks
from the user. Do all the right default actions since we override them
by virtue of our existence. */
GrafPtr port;
Point loc;
short kind;
Handle h;
Rect r;
Boolean ignore;
char key;
long finalTicks;
Boolean returnValue;
returnValue = false; /* always default false */
switch (event->what) {
case keyDown: /* check for <cr> or <enter> */
case autoKey:
key = (char) event->message;
if (key == kCR || key == kENTER) { /* it was a <cr> or <enter> */
GetDItem(dlg, ok, &kind, &h, &r);
HiliteControl((ControlHandle)h, kHilite);
Delay(kHiliteDelay, &finalTicks);
HiliteControl((ControlHandle)h, kDeHilite);
returnValue = true; /* so we handle it */
*item = 1; /* and make the first item hit */
}
break;
case mouseDown: /* we want mouseDowns */
GetPort(&port);
SetPort(dlg);
loc = event->where;
GlobalToLocal(&loc); /* find where clicked */
GetDItem(dlg, dZoneList, &kind, &h, &r); /* get rect for list */
if (PtInRect(loc, &r)) { /* if clicked inside… */
returnValue = true; /* we take care of it */
ignore = LClick(loc, event->modifiers, gList); /* by passing click to list */
}
SetPort(port);
break;
}
return (returnValue);
} /* ListFilter */
void CleanUp_DoZoneList()
{
if (gList != nil) LDispose(gList); /* get rid of list */
if (gErrDlg != nil) DisposDialog(gErrDlg); /* get rid of dialog */
} /* CleanUp_DoZoneList */
pascal void HandleErr_DoZoneList(error, message)
short error; long message;
{
CleanUp_DoZoneList(); /* release junk */
} /* HandleErr_DoZoneList */
void DoZoneList()
/* Put up a modal dialog that shows a list of the zones on the net. Create the dialog
and list, call BuildZoneList to fill it, then wait for the user to click OK. */
{
DialogPtr dlg;
short item, kind;
Handle h;
Rect r, rView, dataBounds;
Cell cSize;
FailInfo fi;
short hor, ver;
gList = nil; /* init some important variables */
dlg = nil;
CatchCFailures(&fi, HandleErr_DoZoneList);
dlg = GetNewDialog(rZoneDialog, nil, (WindowPtr)-1); /* create dialog */
gErrDlg = dlg;
FailnilMsg(dlg, eNoMemory);
/* We center the dialog horizontally and position it vertically one-third the
distance from the menu bar to the bottom of the main device. We do not
check for the dialog extending past the bottom of the device because we
know the dialog is not that big. You may wish to make that check. */
hor = dlg->portRect.right - dlg->portRect.left;
hor = ((screenBits.bounds.right - screenBits.bounds.left) - hor) / 2;
ver = ((screenBits.bounds.bottom - screenBits.bounds.top) - GetMBarHeight()) / 3;
MoveWindow(dlg, hor, ver, false);
GetDItem(dlg, dDefault, &kind, &h, &r);
SetDItem(dlg, dDefault, kind, (Handle) ZoneListDraw, &r);
GetDItem(dlg, dZoneList, &kind, &h, &r);
SetDItem(dlg, dZoneList, kind, (Handle) ZoneListDraw, &r); /* connect drawing void */
rView = r;
rView.right -= kScrollBarWidth; /* adjust rectangle for scroll */
SetRect(&dataBounds, 0, 0, 1, 0); /* init to one-wide list */
SetPt(&cSize, 0, 0);
gList = LNew(&rView, &dataBounds, cSize, 0, (WindowPtr)dlg,
false, false, false, true); /* create with vertical scroll */
FailnilMsg(gList, eNoMemory);
BuildZoneList(); /* put the stuff into the list */
SetPt(&cSize, 0, 0);
LSetSelect(true, cSize, gList); /* select the first guy */
LDoDraw(true, gList); /* turn on the list */
ShowWindow(dlg); /* turn on the dialog */
do {
ModalDialog((ModalFilterProcPtr) ListFilter, &item); /* accept events */
} while (item != ok); /* until he presses 'ok' */
CleanUp_DoZoneList();
Success(&fi);
} /* DoZoneList */
Boolean DoCloseWindow(window)
WindowPtr window;
{
Boolean functionValue = true;
if (IsDAWindow(window))
CloseDeskAcc((short) ((WindowPeek)window)->windowKind);
else
if (IsAppWindow(window)) CloseWindow(window);
return(functionValue);
} /* DoCloseWindow */
void Terminate()
{
WindowPtr aWindow;
Boolean closed;
closed = true;
do {
aWindow = FrontWindow(); /* get the current front window */
if (aWindow != nil)
closed = DoCloseWindow(aWindow); /* close this window */
} while ((closed) && (aWindow != nil)); /* do all windows */
if (closed) ExitToShell(); /* exit if no cancellation */
} /* Terminate */
void AdjustMenus()
{
WindowPtr window;
MenuHandle menu;
window = FrontWindow();
menu = GetMHandle(mFile);
if (IsDAWindow(window)) /* we can allow desk accessories to be closed from the menu */
EnableItem(menu, iClose);
else
DisableItem(menu, iClose); /* but not our traffic light window */
menu = GetMHandle(mEdit);
if (IsDAWindow(window)) { /* a desk accessory might need the edit menu */
EnableItem(menu, iUndo);
EnableItem(menu, iCut);
EnableItem(menu, iCopy);
EnableItem(menu, iPaste);
EnableItem(menu, iClear);
} else { /* but we know we do not */
DisableItem(menu, iUndo);
DisableItem(menu, iCut);
DisableItem(menu, iCopy);
DisableItem(menu, iClear);
DisableItem(menu, iPaste);
}
} /* AdjustMenus */
pascal void HandleMenu(error, message)
short error; long message;
{
HiliteMenu(0); /* unhighlight what MenuSelect (or MenuKey) hilited */
} /* HandleMenu */
void DoMenuCommand(menuResult)
long menuResult;
{
short menuID; /* the resource ID of the selected menu */
short menuItem; /* the item number of the selected menu */
short itemHit;
Str255 daName;
short daRefNum;
Boolean handledByDA ;
Boolean ignore;
FailInfo fi;
CatchCFailures(&fi, (HandlerFuncPtr) HandleMenu);
menuID = HiWord(menuResult); /* use built-ins (for efficiency)... */
menuItem = LoWord(menuResult); /* to get menu item number and menu number */
switch (menuID) {
case mApple:
switch (menuItem) {
case iAbout: /* bring up alert for About */
itemHit = Alert(rAboutAlert, nil);
break;
default: /* all non-About items in this menu are DAs */
GetItem(GetMHandle(mApple), menuItem, daName);
daRefNum = OpenDeskAcc(daName);
break;
}
break;
case mFile:
switch (menuItem) {
case iNew:
DoZoneList();
break;
case iClose:
ignore = DoCloseWindow(FrontWindow());
break;
case iQuit:
Terminate();
break;
}
break;
case mEdit: /* call SystemEdit for DA editing & Multifinder */
handledByDA = SystemEdit(menuItem-1); /* since we don't do any editing */
break;
}
HiliteMenu(0); /* cleanup */
Success(&fi);
} /* DoMenuCommand */
void AdjustCursor(mouse, region)
Point mouse; RgnHandle region;
{
} /* AdjustCursor */
pascal void HandleErr_DoEvent(error, message)
short error;
long message;
{
if (error > 0) AlertUser(0, error);
else AlertUser(error, message);
ExitToShell();
} /* HandleErr_DoEvent */
void DoEvent(event)
EventRecord event;
{
short part;
WindowPtr window;
char key;
FailInfo fi;
Point aPoint;
OSErr err;
CatchCFailures(&fi, (HandlerFuncPtr) HandleErr_DoEvent);
switch (event.what) {
case mouseDown:
part = FindWindow(event.where, &window);
switch (part) {
case inMenuBar: /* process the menu command */
AdjustMenus();
DoMenuCommand(MenuSelect(event.where));
break;
case inSysWindow: /* let the system handle the mouseDown */
SystemClick(&event, window);
break;
case inContent:
break;
case inDrag:
break;
case inGrow:
break;
case inZoomIn:
case inZoomOut:
break;
}
break;
case keyDown: /* check for menukey equivalents */
case autoKey:
key = event.message & charCodeMask;
if (event.modifiers & cmdKey) { /* Command key down */
if (event.what == keyDown) {
AdjustMenus(); /* enable/disable/check menu items properly */
DoMenuCommand(MenuKey(key));
}
}
break;
/* call DoActivate with the window and... */
case activateEvt:
break;
case updateEvt:
break;
/* It is not a bad idea to at least call DIBadMount in response
to a diskEvt, so that the user can format a floppy. */
case diskEvt:
if (HiWord(event.message) != noErr) {
SetPt(&aPoint, kDILeft, kDITop);
err = DIBadMount(aPoint, event.message);
}
case kOSEvent:
switch ((event.message >> 24) & 0x0FF) { /* high byte of message */
case kSuspendResumeMessage:
gInBackground = event.message & kResumeMask;
break;
}
break;
}
Success(&fi);
} /* DoEvent */
void EventLoop()
{
RgnHandle cursorRgn;
Boolean gotEvent;
EventRecord event;
cursorRgn = NewRgn(); /* we’ll pass WNE an empty region the 1st time thru */
do {
if (gHasWaitNextEvent) /* put us 'asleep' forever under Multifinder */
gotEvent = WaitNextEvent(everyEvent, &event, MAXLONG, cursorRgn);
else {
SystemTask(); /* must be called if using GetNextEvent */
gotEvent = GetNextEvent(everyEvent, &event);
}
if (gotEvent) {
AdjustCursor(event.where, cursorRgn); /* make sure we have the right cursor */
DoEvent(event);
}
AdjustCursor(event.where, cursorRgn);
} while (true); /* loop forever; we quit through an ExitToShell */
} /* EventLoop */
void main()
{
MaxApplZone(); /* expand the heap so code segments load at the top */
InitUFailure();
Initialize(); /* initialize the program */
UnloadSeg(Initialize); /* note that Initialize must not be in Main! */
EventLoop(); /* call the main event loop */
} /* main */